<?php
/**
 * Eka Framework 0.3.0
 *
 * @copyright Copyright (c) 2008 Alexey Yu. Chuprina <656b61@gmail.com> (http://php-eka.googlecode.com)
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 *
 * @version $Id$
 */

require_once 'Eka/Db/Statement/Abstract.php';

/**
 * Eka_Db_Statement_Pdo
 *
 * @package Db
 * @subpackage Statement
 */
class Eka_Db_Statement_Pdo extends Eka_Db_Statement_Abstract
{
	/**
	 * PDOStatement object
	 *
	 * @var PDOStatement
	 */
	protected $stmt;

	/**
	 * Prepare a string SQL statement and create a statement object
	 *
	 * @param string $sql
	 * @return void
	 * @throws Eka_Db_Statement_Exception
	 */
	protected function prepare($sql)
	{
		try {
			$this->stmt = $this->adapter->getConnection()->prepare($sql);
		} catch (PDOException $e) {
			include_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
	}

	/**
	 * Closes the cursor, allowing the statement to be executed again
	 *
	 * @return bool
	 * @throws Eka_Db_Statement_Exception
	 */
	public function closeCursor()
	{
		try {
			return $this->stmt->closeCursor();
		} catch (PDOException $e) {
			include_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}

	/**
	 * Returns the number of rows affected by the execution
	 *
	 * @return int
	 * @throws Eka_Db_Statement_Exception
	 */
	public function rowCount()
	{
		try {
			return $this->stmt->rowCount();
		} catch (PDOException $e) {
			include_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}
	
	/**
	 * Returns the number of columns in the result set
	 *
	 * @return int The number of columns
	 * @throws Eka_Db_Statement_Exception
	 */
	public function columnCount()
	{
		try {
			return $this->stmt->columnCount();
		} catch (PDOException $e) {
			include_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}

	/**
	 * Retrieves the error code, if any, associated with the last operation on
	 * the statement handle
	 *
	 * @return string error code
	 * @throws Eka_Db_Statement_Exception
	 */
	public function errorCode()
	{
		try {
			return $this->stmt->errorCode();
		} catch (PDOException $e) {
			include_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}

	/**
	 * Retrieves an array of error information, if any, associated with the last operation on the statement handle
	 *
	 * @return array
	 * @throws Eka_Db_Statement_Exception
	 */
	public function errorInfo()
	{
		try {
			return $this->stmt->errorInfo();
		} catch (PDOException $e) {
			require_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}

	/**
	 * Executes a prepared statement
	 *
	 * @param array $bind
	 * @return bool
	 * @throws Eka_Db_Statement_Exception
	 */
	public function execute(array $bind = null)
	{
		$this->lastBind = $bind;
		$this->adapter->log($this->stmt->queryString, $bind);
		try {
			return $this->stmt->execute($bind);
		} catch (PDOException $e) {
			ob_start();
			var_dump($bind);
			$bind = ob_get_clean();
			require_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage()
				. "\nQuery: " . $this->stmt->queryString
				. "\nBind: " . $bind . "\n"
			);
		}
		return null;
	}
	
	/**
	 * Fetches a row from the result set as an array indexed by both column name and 0-indexed column number
	 *
	 * @return array
	 */
	public function fetch()
	{
		try {
			return $this->stmt->fetch(PDO::FETCH_BOTH);
		} catch (PDOException $e) {
			require_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}
	
	/**
	 * Fetches a row from the result set as an array indexed by column name
	 *
	 * @return array
	 */
	public function fetchAssoc()
	{
		try {
			return $this->stmt->fetch(PDO::FETCH_ASSOC);
		} catch (PDOException $e) {
			require_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}
	
	/**
	 * Fetches a row from the result set as an array indexed by column number, starting at column 0
	 *
	 * @return array
	 */
	public function fetchNum()
	{
		try {
			return $this->stmt->fetch(PDO::FETCH_NUM);
		} catch (PDOException $e) {
			require_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}
	
	/**
	 * Returns a single column from the next row of a result set
	 *
	 * @param int $col Position of the column to fetch
	 * @return string
	 */
	public function fetchColumn($pos = 0)
	{
		try {
			return $this->stmt->fetchColumn($pos);
		} catch (PDOException $e) {
			require_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}
	
	/**
	 * Returns all rows from the result set as an array indexed by both column name and 0-indexed column number
	 *
	 * @return array Collection of rows
	 */
	public function fetchAll()
	{
		try {
			return $this->stmt->fetchAll(PDO::FETCH_BOTH);
		} catch (PDOException $e) {
			require_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}
	
	/**
	 * Returns all rows from the result set as an array indexed by column name
	 *
	 * @return array Collection of rows
	 */
	public function fetchAllAssoc()
	{
		try {
			return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
		} catch (PDOException $e) {
			require_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}
	
	/**
	 * Returns all rows from the result set as an array indexed by column number, starting at column 0
	 *
	 * @return array Collection of rows
	 */
	public function fetchAllNum()
	{
		try {
			return $this->stmt->fetchAll(PDO::FETCH_NUM);
		} catch (PDOException $e) {
			require_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}
	
	/**
	 * @param int $col Position of the column to fetch
	 * @return array Collection of columns
	 */
	public function fetchAllColumn($pos = 0)
	{
		$result = array();
		try {
			while (false !== ($row = $this->stmt->fetchColumn($pos))) {
				$result[] = $row;
			}
			return $result;
		} catch (PDOException $e) {
			require_once 'Eka/Db/Statement/Exception.php';
			throw new Eka_Db_Statement_Exception($e->getMessage());
		}
		return null;
	}
}
